#ifndef CIGUI_MAINWINDOW_H
#define CIGUI_MAINWINDOW_H

#include <QMainWindow>
#include <QXmlDefaultHandler>
#include <string>

#include "ViewsContainer.h"
#include "PropertyGroup.h"
#include "../Operations/OperationManager.h"

namespace CIGui {
    /**
     * This class represents the application main window     
     **/
    class MainWindow : public QMainWindow {

        Q_OBJECT      

    public:
        MainWindow (QWidget *parent = 0);               //Contructor    
        virtual ~MainWindow();                          //Destructor

        //CONSTANTS DECLARATION
        static const QString STYLE_SHEET;

    public slots:                                                           
        void SetViewsStatus (int status, int opID=0);   //Slot method to set the status of the 3D views

        //Slots for opreations
        void UndoOperation();                           //Slot method called to undo the last user operation 
        void RedoOperation();                           //Slot method called to redo the last user operation canceled 
        void DeleteOperation();                         //Slot method called to delete the selected primitives
        void DuplicateOperation();                      //Slot method called to duplicate the selected primitives
        void DoOperation (int opID);                    //Slot method called to execute the operation identified by opID

        void About();                                   //Slot method called to show the about box
        void New();                                     //Slot method called to create a new scene
        void Open();                                    //Slot method called to open a saved scene
        void Save();                                    //Slot method called to save the current scene
        void SaveAs();                                  //Slot method called to save the current scene

        void UpdateViews();                             //Slot method called to updates the 3D views 

    protected:        
        //Content
        QWidget* content;                       //The window's content

        //Layouts
        QHBoxLayout* contentLayout;             //The window's content layout    

        //Views
        ViewsContainer* viewsContainer;         //The views'container  
        std::vector<CIView::View*> views;       //The 3D views
        CIView::Scene scene;                    //The 3D scene

        //Controls tab                                                        //TODO -> Use DockWidgets!? Decide how to visualize controls
        QTabWidget* controls;                   //The controls tab container
        QWidget* modelingControls;              //The modeling controls
        QWidget* materialsControls;             //The materials'controls

        //Menus         
        QMenu* fileMenu;                        //The file menu
        QMenu* editMenu;                        //The edit menu
        QMenu* viewMenu;                        //The view menu
        QMenu* toolsMenu;                       //The tools menu
        QMenu* helpMenu;                        //The help menu

        //Toolbars      
        QActionGroup* operationsActionGroup;    //The group of action connected with operations
        QToolBar* operationsToolBar;            //The file toolbar                //TODO -> What do toolbars contain?
        QToolBar* editToolBar;                  //The edit tollbar

        //Actions
        QAction* newAct;                        //The new action
        QAction* openAct;                       //The open action
        QAction* saveAct;                       //The save action   
        QAction* saveAsAct;                     //The "save as" action        
        QAction* aboutAct;                      //The about action        
        QAction* quitAct;                       //The quit action
        QAction* undoAct;                       //The undo action
        QAction* redoAct;                       //The redo action
        QAction* deleteAct;                     //The delete action
        QAction* duplicateAct;                  //The duplicate action
        QAction* selectAllAct;                  //The action to select all the primitives
        QAction* deselectAllAct;                //The action to deselect all the primitives
        QAction* invertSelectionAct;            //The action to invert the primitives selection status
        QAction* hideAct;                       //The action to hide the selected primitives 
        QAction* unhideAct;                     //The action to unhide all the primitives 

        //Current loaded/saved file name
        QString currentFileName;                //The current loaded/saved file name        

        //Operations'Actions 
        QAction* cameraControlAct;              //The action to set the status of the application for camera control
        QAction* selectGeometriesAct;           //The action to set the status of the application for geometries selection
        QAction* selectFacesAct;                //The action to set the status of the application for faces selection
        QAction* selectVerticesAct;             //The action to set the status of the application for vertices selection
        QAction* translateAct;                  //The action to set the status of the application for primitives translation
        QAction* scaleAct;                      //The action to set the status of the application for primitives scaling
        QAction* rotateAct;                     //The action to set the status of the application for primitives rotation
        QAction* extrudeAct;                    //The action to set the status of the application for primitives extrusion
        QAction* createVertexAct;               //The action to set the status of the application for vertex creation        
        QAction* createTriangleAct;             //The action to set the status of the application for triangle creation        
        QAction* createTriangleStripAct;        //The action to set the status of the application for triangle strip creation                
        QAction* createRectangleAct;            //The action to set the status of the application for rectangle creation        
        QAction* createCuboidAct;               //The action to set the status of the application for cuboid creation        
        QAction* createSphereAct;               //The action to set the status of the application for sphere creation           
        QAction* createCylinderAct;             //The action to set the status of the application for cylinder creation        
        QAction* createConeAct;                 //The action to set the status of the application for cone creation        
        QAction* createTorusAct;                //The action to set the status of the application for torus creation        
        
        //Operations manager
        CIOps::OperationManager operationManager;      //The operations manager
        
        //Utility methods
        void CreateActions();                   //Method called to create the actions
        void CreateContent();                   //Method called to create the window's content
        void CreateLayouts();                   //Method called to create the window's layouts
        void CreateMenus();                     //Method called to create the window's menus
        void CreateStatusBar();                 //Method called to create the window's status bar
        void CreateToolbars();                  //Method called to create the window's toolbars
        void CreateViews();                     //Method called to create the gl view
        void CreateControlsTab();               //Method called to create the controls tab
        void CreateModelingControls();          //Method called to create the modeling controls        
        void CreateMaterialsControls();         //Method called to create the materials'control
        
        //Method called to create and get a widget containing a tool button 
        //according to the action received as input and inserting it in the button group
        QWidget* ToolButtonWidget (QButtonGroup* buttonGroup, QAction* act);                       
        
        //Method called to create and get a widget containing the properties for a transformation operation
        PropertyGroup* TransformationPropertyGroup (CIOps::ActionOpCreation* act, QString name, QString default_value);

        //Method called to create and get a widget containing the radio buttons for a transformation operation
        QWidget* TransformationRadioButtons();      

        //virtual bool event (QEvent* e);                 //Virtual method called whenever the widget receives an event        
        virtual void closeEvent (QCloseEvent *e);       //Virtual method called whenever the widget receives a close event        

        //Methods for scene saving/loading
        void SaveSceneAsCI3D (const char* filename);
        static void SaveGeometryAsCI3D (std::pair<CIGeom::Geometry*, std::ofstream*>& pair);
        bool LoadSceneFromCI3D (const char* filename);
       
        //SAX XML handler (For scene loading)
        class CI3DHandler : public QXmlDefaultHandler {
            CIView::Scene& scene;

            CIGeom::Geometry* currentGeometry;
            QString geometryName;            

            QString currentText;

            QString errorStr; 

            bool metCI3DTag;

        public:
            CI3DHandler (CIView::Scene& s) : scene (s) {}

            bool startElement(const QString &namespaceURI, const QString &localName,
                              const QString &qName, const QXmlAttributes &attributes);
            bool endElement(const QString &namespaceURI, const QString &localName,
                            const QString &qName);
            bool characters(const QString &str);
            bool fatalError(const QXmlParseException &exception);
            QString errorString() const;
            
        };        
    };
}

#endif // CIGUI_MAINWINDOW_H
